import { Init, Inject, Provide, httpError } from '@midwayjs/core'
import { InjectEntityModel } from '@midwayjs/typegoose'
import { ReturnModelType } from '@typegoose/typegoose'
import { IUserOptions } from '../interface.js'
import { User } from '../entity/user.js'
import { JwtService } from '@midwayjs/jwt'
import { randomUUID } from 'node:crypto'
import { createHash } from 'crypto'
import { RolesService } from './roles.service.js'

@Provide()
export class UserService {
  @Inject()
  jwtService: JwtService

  @Inject()
  rolesService: RolesService

  @InjectEntityModel(User)
  userModel: ReturnModelType<typeof User>

  async insertMany(userData: IUserOptions[]): Promise<any> {
    for (const item of userData) {
      const userInfo = await this.userModel
        .findOne({ username: item.username })
        .exec()
      if (userInfo) throw new httpError.ForbiddenError('用户已存在')
      else {
        const user: any = item
        if (!user.id) user.id = randomUUID()
      }
    }
    const createdUser = this.userModel.insertMany(userData)
    return createdUser
  }

  async find(query?): Promise<any> {
    const { currentPage, pageSize } = query ?? {}
    const options: any = {
      sort: { _id: -1 }
    }

    if (currentPage) {
      options.skip = (currentPage - 1) * pageSize
      delete query.currentPage
    }

    if (pageSize) {
      options.limit = +pageSize
      delete query.pageSize
    }

    if (!query.username || query.username === 'admin')
      query.username = /^(?!admin)/

    const total = await this.userModel.countDocuments(query).exec()
    const data = await this.userModel.find(query, null, options).exec()

    return {
      total: total,
      data: data
    }
  }

  async findOne(data): Promise<User | undefined> {
    return this.userModel.findOne(data).exec()
  }

  async updateOne(data): Promise<any> {
    Reflect.deleteProperty(data, '_id')
    return this.userModel.updateOne({ id: data.id }, { $set: data }).exec()
  }

  async deleteOne(data): Promise<any> {
    if (data) {
      const deletedUser = await this.userModel.deleteOne(data).exec()
      return deletedUser
    }
  }

  async login(data) {
    const userInfo: any = await this.findOne(data)

    if (!userInfo || userInfo?.password !== data.password) {
      throw new httpError.ForbiddenError('账号密码错误')
    } else {
      const payload = { username: userInfo.username, roles: userInfo.roles }

      return Object.assign(
        { token: await this.jwtService.sign(payload) },
        userInfo.toObject()
      )
    }
  }

  async register(data) {
    const userInfo: any = await this.findOne(data)
    if (userInfo) throw new httpError.ForbiddenError('用户已存在')
    else {
      const userInfo: any = (
        await this.insertMany([
          {
            username: data.username,
            password: data.password,
            roles: ['default'],
            nickname: '用户' + data.username,
            department: '研发部',
            position: '职员'
          }
        ])
      )[0]

      const payload = { username: userInfo.username, role: userInfo.role }
      return Object.assign(
        { token: await this.jwtService.sign(payload) },
        userInfo.toObject()
      )
    }
  }

  @Init()
  async initUsers() {
    const roleId: any = await this.rolesService
      .initRoles()
      .then((res) => res.id)
    const data: any = { username: 'admin', password: hashEncrypt('admin123') }

    const userInfo: any = await this.findOne(data)
    if (!userInfo) {
      await this.insertMany([
        {
          username: data.username,
          password: data.password,
          roles: [roleId],
          nickname: '超级管理员',
          department: '',
          position: ''
        }
      ])
    }
  }
}

// sha256哈希加密
export function hashEncrypt(message: string) {
  const hashHex = createHash('sha256').update(message).digest('hex')

  return hashHex
}
